using Vwf.Tools;

namespace Vwf.Vwt {
	
	public class ParserVala : Parser {
		public BlockVala myContent { get { return (BlockVala)content; } }
		public ParserVala() {
			content = new BlockVala();
			blockTypes = new string[] { 
				"i", "init", 
				"p", "prerender", 
				"r", "render", 
				"=", "e", "eval", 
				"=e", "ee", "evalescape",
				"Vala"
			};
		}
		public enum Mode { Template, CodeBlock, Expression }
		public Mode mode;
		public override void parse() throws EDParser, EDStrParser {
			string cStart = strParser.createCursor();
			strParser.storeCursor(cStart);
			string[] chunks = new string[] {} ;
			switch(mode) {
				case Mode.Template: chunks = new string[] { "?>", "//", "/*", "\"\"\"", "\"" }; break;
				case Mode.CodeBlock: chunks = new string[] { "?>", "//", "/*", "\"\"\"", "\"", "{", "}" }; break;
				case Mode.Expression: chunks = new string[] { "?>", "//", "/*", "\"\"\"", "\"", "(", ")" }; break;
			}
			logMsg("Mode: " + mode.to_string());
			int brakeLevel = 0;
			do {
				if (strParser.findAnyNext(chunks)) {
					// add(new BlockHtml(strParser.substring(cStart)));
					
					switch (strParser.lastChunk) {
						case "?>":
							myContent.code = (strParser.substring(cStart));
							strParser.toEndChunk();
							return;
						case "//":
							strParser.toEndChunk();
							if (!strParser.findNext("\n")) throw new EDParser.UnexpectedEOF("Unterminated line comment");
							strParser.toEndChunk();
							break;
						case "/*":
							strParser.toEndChunk();
							if (!strParser.findNext("*/")) throw new EDParser.UnexpectedEOF("Unterminated block comment");
							strParser.toEndChunk();
							break;
						case "\"\"\"":
							strParser.toEndChunk();
							if (!strParser.findNext("\"\"\"")) throw new EDParser.UnexpectedEOF("Unterminated verbatim string");
							strParser.toEndChunk();
							break;
						case "\"":
							strParser.toEndChunk();
							do {
								if (!strParser.findAnyNext(new string[] { "\\\"", "\"" })) throw new EDParser.UnexpectedEOF("Unterminated string");
								strParser.toEndChunk();
								// if (strParser.lastChunk == "\n") throw new EDParser.UnexpectedEOF("String");
								
							} while (strParser.lastChunk != "\"");
							break;
						case "{":
						case "(":
							strParser.toEndChunk();
							brakeLevel++;
							logMsg("< brakolevel=" + brakeLevel.to_string());
							break;
						case "}":
						case ")":
							strParser.toEndChunk();
							brakeLevel--;
							logMsg("> brakolevel=" + brakeLevel.to_string());
							if (brakeLevel <= 0) {
								myContent.code = (strParser.substring(cStart));
								strParser.toEndChunk();
								return;
							}
							break;
					}
				}
			} while (true);
		}
		public override void setBlockType(string blockType) {
			switch(blockType) {
				case "i":
				case "init":
					myContent.type = BlockVala.Type.Init;
					break;
				case "p":
				case "prerender":
					myContent.type = BlockVala.Type.PreRender;
					break;
				case "r":
				case "render":
					myContent.type = BlockVala.Type.Render;
					break;
				case "=":
				case "e":
				case "eval":
					myContent.type = BlockVala.Type.Eval;
					break;
				case "=e":
				case "ee":
				case "evalescape":
					myContent.type = BlockVala.Type.EvalEscape;
					break;
			}
			logMsg(blockType + " => " + myContent.type.to_string());
		}
	}
}
